package com.bagri.tools.vvm.ui; import com.bagri.tools.vvm.event.*; import com.bagri.tools.vvm.model.*; import com.bagri.tools.vvm.service.*; import com.bagri.tools.vvm.util.ErrorUtil; import com.bagri.tools.vvm.util.Icons; import com.sun.tools.attach.VirtualMachine; import com.sun.tools.attach.VirtualMachineDescriptor; import com.sun.tools.attach.spi.AttachProvider; import com.sun.tools.visualvm.tools.jmx.JmxModel; import javax.management.*; import javax.management.remote.JMXConnectionNotification; import javax.management.remote.JMXConnector; import javax.management.remote.JMXConnectorFactory; import javax.management.remote.JMXServiceURL; import javax.swing.*; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.TreePath; import java.awt.*; import java.awt.event.*; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.File; import java.io.IOException; import java.util.HashMap; import java.util.logging.Logger; public class BagriMainPanel extends JPanel implements NotificationListener, PropertyChangeListener { private static final Logger LOGGER = Logger.getLogger(BagriMainPanel.class.getName()); private final MainTreePanel mainTree; private final JSplitPane splitPane; private final UserManagementService userManagementService; private final ClusterManagementService clusterManagementService; private final SchemaManagementService schemaManagementService; private final EventBus<ApplicationEvent> eventBus = new EventBus<ApplicationEvent>(); private UserManagementPanel userManagementPanel; private ClusterManagementPanel clusterManagementPanel; private BagriManagementPanel bagriManagementPanel; private SchemaManagementPanel schemaManagementPanel; // TODO: Remove cache entry if schema is deleted. private HashMap<String, SchemaPanel> schemaCache = new HashMap<String, SchemaPanel>(); public BagriMainPanel(BagriServiceProvider serviceProvider) { // Services userManagementService = serviceProvider.getUserManagement(); clusterManagementService = serviceProvider.getClusterManagement(); schemaManagementService = serviceProvider.getSchemaManagement(); setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS)); // Main tree mainTree = createTree(); Dimension minimumSize = new Dimension(150, 100);//TODO: Move to constants JScrollPane treeScrollPane = new JScrollPane(mainTree); treeScrollPane.setMinimumSize(minimumSize); JPanel emptyPanel = new JPanel(); JScrollPane rightScrollPane = new JScrollPane(emptyPanel); //Create a split pane with the two scroll panes in it. splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, treeScrollPane, rightScrollPane); splitPane.setDividerLocation(200);//TODO: Move to constants add(splitPane); setOpaque(true); eventBus.addEventHandler(new EventHandler<ApplicationEvent>() { @Override public void handleEvent(ApplicationEvent e) { if (ClusterManagement.CLUSTER_STATE_CHANGED.equals(e.getCommand())) { try { java.util.List<Node> nodes = clusterManagementService.getNodes(); mainTree.setNodes(nodes); } catch (ServiceException e1) { ErrorUtil.showError(BagriMainPanel.this, e1); } } if (SchemaManagement.SCHEMA_STATE_CHANGED.equals(e.getCommand())) { try { java.util.List<Schema> schemas = schemaManagementService.getSchemas(); mainTree.setSchemas(schemas); } catch (ServiceException e1) { ErrorUtil.showError(BagriMainPanel.this, e1); } } if (BagriManager.MANAGEMENT_SECTION_SELECTED.equals(e.getCommand())) { TreePath tp = mainTree.findTreePath(e.getSource().toString()); if (null != tp) { mainTree.setSelectionPath(tp); } } } }); } protected JComponent makeTextPanel(String text) { JPanel panel = new JPanel(false); JLabel filler = new JLabel(text); filler.setHorizontalAlignment(JLabel.CENTER); panel.setLayout(new GridLayout(1, 1)); panel.add(filler); return panel; } private MainTreePanel createTree() { final MainTreePanel tree = new MainTreePanel(); java.util.List<Node> nodes = null; try { nodes = clusterManagementService.getNodes(); tree.setNodes(nodes); } catch (ServiceException e) { LOGGER.throwing(BagriMainPanel.class.getName(), "createTree", e); ErrorUtil.showError(BagriMainPanel.this, e); } java.util.List<Schema> schemas = null; try { schemas = schemaManagementService.getSchemas(); tree.setSchemas(schemas); } catch (ServiceException e) { LOGGER.throwing(BagriMainPanel.class.getName(), "createTree", e); ErrorUtil.showError(BagriMainPanel.this, e); } java.util.List<User> users = null; try { users = userManagementService.getUsers(); tree.setUsers(users); } catch (ServiceException e) { LOGGER.throwing(BagriMainPanel.class.getName(), "createTree", e); ErrorUtil.showError(BagriMainPanel.this, e); } tree.addMouseListener ( new MouseAdapter() { public void mousePressed ( MouseEvent e ) { if ( SwingUtilities.isRightMouseButton ( e ) ) { int row = tree.getClosestRowForLocation(e.getX(), e.getY()); tree.setSelectionRow(row); TreePath path = tree.getPathForLocation ( e.getX (), e.getY () ); Rectangle pathBounds = tree.getPathBounds(path); if ( pathBounds != null && pathBounds.contains ( e.getX (), e.getY ()) && null != path ){ DefaultMutableTreeNode node = (DefaultMutableTreeNode) path.getLastPathComponent(); final Object o = node.getUserObject(); // if (o instanceof User) { // JPopupMenu menu = new JPopupMenu (); // JMenuItem menuItem = new JMenuItem ( "Remove User" ); // menuItem.addActionListener(new ActionListener() { // @Override // public void actionPerformed(ActionEvent e) { // try { // userManagementService.deleteUser(((User) o).getUserName()); // } catch (ServiceException e1) { // LOGGER.throwing(BagriMainPanel.class.getName(), "onRemoveUser", e1); // } // } // }); // menu.add ( menuItem ); // menu.show ( tree, e.getX(), e.getY() ); // } if (o instanceof UserManagement) { JPopupMenu menu = new JPopupMenu (); JMenuItem menuItem = new JMenuItem ( "Add User" ); menuItem.setIcon(Icons.ADD_ICON); menuItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { AddUserDialog dlg = new AddUserDialog(BagriMainPanel.this); dlg.setSuccessListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { final AddUserDialog src = (AddUserDialog) e.getSource(); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { try { userManagementService.addUser(src.getUsername(), src.getPassword()); eventBus.fireEvent(new ApplicationEvent(src, "AddUser")); } catch (ServiceException e1) { LOGGER.throwing(BagriMainPanel.class.getName(), "onAddUser", e1); ErrorUtil.showError(BagriMainPanel.this, e1); } } }); } }); dlg.setVisible(true); } }); menu.add ( menuItem ); menu.show ( tree, e.getX(), e.getY() ); } } } } } ); tree.addTreeSelectionListener(new TreeSelectionListener() { @Override public void valueChanged(TreeSelectionEvent e) { DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent(); if (node == null) return; int dividerLocation = splitPane.getDividerLocation(); Object nodeInfo = node.getUserObject(); if (nodeInfo instanceof BagriManager) { splitPane.setRightComponent(getBagriManagementPanel()); } else if (nodeInfo instanceof ClusterManagement) { splitPane.setRightComponent(getClusterManagementPanel()); } else if (nodeInfo instanceof Node) { // TODO: cache panels per Node (template) splitPane.setRightComponent(new NodeManagementPanel(BagriMainPanel.this.clusterManagementService, (Node)nodeInfo)); } else if (nodeInfo instanceof SchemaManagement) { splitPane.setRightComponent(getSchemaManagementPanel()); } else if (nodeInfo instanceof Schema) { Schema s = (Schema) nodeInfo; SchemaPanel panel = schemaCache.get(s.getSchemaName()); if (null == panel) { panel = new SchemaPanel(schemaManagementService, eventBus, s); schemaCache.put(s.getSchemaName(), panel); } splitPane.setRightComponent(panel); } else if (nodeInfo instanceof UserManagement) { splitPane.setRightComponent(getUserManagementView()); } else if (nodeInfo instanceof User) { // TODO: implement it.. //User u = (User) nodeInfo; splitPane.setRightComponent(new DualListBox()); } else { JTabbedPane tabbedPane = new JTabbedPane(); tabbedPane.addTab(nodeInfo.toString(), makeTextPanel(nodeInfo.toString() + " placeholder")); splitPane.setRightComponent(tabbedPane); } splitPane.setDividerLocation(dividerLocation); } }); return tree; } private UserManagementPanel getUserManagementView() { if (null == userManagementPanel) { userManagementPanel = new UserManagementPanel(userManagementService, eventBus); } return userManagementPanel; } private ClusterManagementPanel getClusterManagementPanel() { if (null == clusterManagementPanel) { clusterManagementPanel = new ClusterManagementPanel(clusterManagementService, eventBus); } return clusterManagementPanel; } private SchemaManagementPanel getSchemaManagementPanel() { if (null == schemaManagementPanel) { schemaManagementPanel = new SchemaManagementPanel(schemaManagementService, eventBus); } return schemaManagementPanel; } private BagriManagementPanel getBagriManagementPanel() { if (null == bagriManagementPanel) { bagriManagementPanel = new BagriManagementPanel(eventBus); } return bagriManagementPanel; } /* private String[] getSchemas(MBeanServerConnection connection) { try { Object res = connection.invoke(new ObjectName("com.bagri.db:type=Management,name=SchemaManagement"), "getSchemaNames", null, null); return (String[]) res; } catch (Exception e) { LOGGER.throwing(this.getClass().getName(), "getSchemaNames", e); return new String[]{}; } } */ /* notification listener: handleNotification */ @Override public void handleNotification(final Notification notification, Object handback) { EventQueue.invokeLater(new Runnable() { public void run() { if (notification instanceof JMXConnectionNotification) { if (JMXConnectionNotification.FAILED.equals(notification.getType()) || JMXConnectionNotification.CLOSED.equals(notification.getType())) { dispose(); } } if (notification instanceof MBeanServerNotification) { ObjectName mbean = ((MBeanServerNotification) notification).getMBeanName(); if (notification.getType().equals( MBeanServerNotification.REGISTRATION_NOTIFICATION)) { if ("User".equals(mbean.getKeyProperty("type"))) { eventBus.fireEvent(new ApplicationEvent(this, UserManagement.USER_STATE_CHANGED)); } if ("Node".equals(mbean.getKeyProperty("type"))) { eventBus.fireEvent(new ApplicationEvent(this, ClusterManagement.CLUSTER_STATE_CHANGED)); } if ("Schema".equals(mbean.getKeyProperty("type"))) { eventBus.fireEvent(new ApplicationEvent(this, SchemaManagement.SCHEMA_STATE_CHANGED)); } } else if (notification.getType().equals( MBeanServerNotification.UNREGISTRATION_NOTIFICATION)) { if ("User".equals(mbean.getKeyProperty("type"))) { eventBus.fireEvent(new ApplicationEvent(this, UserManagement.USER_STATE_CHANGED)); } if ("Node".equals(mbean.getKeyProperty("type"))) { eventBus.fireEvent(new ApplicationEvent(this, ClusterManagement.CLUSTER_STATE_CHANGED)); } if ("Schema".equals(mbean.getKeyProperty("type"))) { eventBus.fireEvent(new ApplicationEvent(this, SchemaManagement.SCHEMA_STATE_CHANGED)); } } } } }); } public void dispose() { removePropertyChangeListener(this); mainTree.setEnabled(false); splitPane.getRightComponent().setEnabled(false); splitPane.setEnabled(false); } @Override public void propertyChange(PropertyChangeEvent evt) { if (JmxModel.CONNECTION_STATE_PROPERTY.equals(evt.getPropertyName())) { JmxModel.ConnectionState newState = (JmxModel.ConnectionState) evt.getNewValue(); switch (newState) { case DISCONNECTED: dispose(); break; } } } //--------------------------- For testing and debugging only ---------------------------------------------------------// public static void main(String[] args) throws Exception { // Look and feel UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); MBeanServerConnection mbsc = getMBeanServerConnection(); Object o = null; try { o = mbsc.getObjectInstance(new ObjectName("com.bagri.db:type=Management,name=ClusterManagement")); } catch (Exception e) { e.printStackTrace(); } if (o != null) { BagriServiceProvider bsp = DefaultServiceProvider.getInstance(mbsc); final BagriMainPanel panel = new BagriMainPanel(bsp); WindowListener windowAdapter = new WindowAdapter() { public void windowClosing(WindowEvent e) {System.exit(0);} }; JFrame frame = new JFrame("Bagri Manager"); frame.addWindowListener(windowAdapter); frame.getContentPane().add("Center", panel); frame.pack(); frame.setSize(new Dimension(800, 500)); frame.setLocationRelativeTo(null); frame.setVisible(true); } } private static MBeanServerConnection getMBeanServerConnection() throws Exception { final AttachProvider attachProvider = AttachProvider.providers().get(0); VirtualMachineDescriptor descriptor = null; for (VirtualMachineDescriptor virtualMachineDescriptor : attachProvider.listVirtualMachines()) { if (pickThisOne(virtualMachineDescriptor)) { descriptor = virtualMachineDescriptor; final VirtualMachine virtualMachine = attachProvider.attachVirtualMachine(descriptor); final JMXServiceURL target = getURLForVM(virtualMachine); final JMXConnector connector = JMXConnectorFactory.connect(target); final MBeanServerConnection remote = connector.getMBeanServerConnection(); try { Object o = remote.getObjectInstance(new ObjectName("com.bagri.db:type=Management,name=ClusterManagement")); if (null != o) { break; } } catch (Exception e) { // Swallow for now } } } if (descriptor == null) throw new RuntimeException("Bagri VM not found"); final VirtualMachine virtualMachine = attachProvider.attachVirtualMachine(descriptor); final JMXServiceURL target = getURLForVM(virtualMachine); final JMXConnector connector = JMXConnectorFactory.connect(target); final MBeanServerConnection remote = connector.getMBeanServerConnection(); return remote; } private static boolean pickThisOne(VirtualMachineDescriptor virtualMachineDescriptor) { if ("com.bagri.server.hazelcast.BagriCacheServer".equals(virtualMachineDescriptor.displayName())) { return true; } return false; } private static JMXServiceURL getURLForVM(VirtualMachine vm) throws Exception { final String CONNECTOR_ADDRESS = "com.sun.management.jmxremote.localConnectorAddress"; // attach to the target application // final VirtualMachine vm = VirtualMachine.attach(pid); // get the connector address String connectorAddress = vm.getAgentProperties().getProperty(CONNECTOR_ADDRESS); // no connector address, so we start the JMX agent if (connectorAddress == null) { String agent = vm.getSystemProperties().getProperty("java.home") + File.separator + "lib" + File.separator + "management-agent.jar"; vm.loadAgent(agent); // agent is started, get the connector address connectorAddress = vm.getAgentProperties().getProperty(CONNECTOR_ADDRESS); System.out.println("Starting up a new JMX agent: " + agent); assert connectorAddress != null; } return new JMXServiceURL(connectorAddress); } }